package com.sip.stream.utils.zfy.encoder;

import android.media.MediaCodec;
import android.media.MediaCodecList;
import android.media.MediaCrypto;
import android.media.MediaFormat;
import android.util.Log;
import android.view.Surface;

import com.sip.stream.media.ZFYMediaManager;
import com.sip.stream.utils.zfy.GSMediaSampleData;
import com.sip.stream.utils.zfy.consumer.IGSMediaObserver;
import com.sip.stream.utils.zfy.consumer.IGSVideoEncoderConsumer;

import java.io.IOException;
import java.nio.ByteBuffer;

public class GSH264Encoder extends AbstractMediaCodecEncoder implements IGSVideoEncoder {
    private static final String TAG = "GSH264Encoder";

    private static final int TIME_OUT = 10000;
    private IGSVideoEncoderConsumer listener;
    private IGSMediaObserver<IGSNV12Consumer> observer;
    private int frameRate = 25;
    private long lastDesTimestamp_be = 0;
    private int fpscounter_be = 0;
    private long lastDesTimestamp_ae = 0;
    private int fpscounter_ae = 0;

    @Override
    public void setForcedInterval(int i) {
    }

    @Override
    public void setPerformanceLevel(int i) {
    }

    @Override
    public void startEncode() {
    }

    public GSH264Encoder(int width, int height, int bitrate, int i4) {
        setUpMediaCodec(width, height, bitrate, i4);
    }

    private boolean setUpMediaCodec(int width, int height, int bitrate, int frameRate) {
        Log.i(TAG, "创建264编码器 " + width + "x" + height + " bitRate = " + ((bitrate / 1024) / 1024) + "mbps frameRate = " + frameRate);
        MediaFormat createVideoFormat = MediaFormat.createVideoFormat("video/avc", width, height);
        createVideoFormat.setInteger("color-format", 2135033992);
        createVideoFormat.setInteger("bitrate", bitrate);
        createVideoFormat.setInteger("frame-rate", frameRate);
        createVideoFormat.setInteger("i-frame-interval", 1);
        createVideoFormat.setInteger("level", 4096);
        if (new MediaCodecList(1).findEncoderForFormat(createVideoFormat) == null) {
            Log.i(TAG, "创建264编码器失败,找不到合适的Format");
            return false;
        }
        try {
            this.mediaCodec = MediaCodec.createEncoderByType("video/avc");
            try {
                this.mediaCodec.configure(createVideoFormat, (Surface) null, (MediaCrypto) null, 1);
                Log.i(TAG, "创建264编码器成功");
                this.mediaCodec.start();
                return true;
            } catch (MediaCodec.CodecException e) {
                Log.i(TAG, "创建264编码器失败" + e.getLocalizedMessage());
                e.printStackTrace();
                return false;
            }
        } catch (IOException e2) {
            Log.i(TAG, "创建264编码器失败" + e2.getLocalizedMessage());
            e2.printStackTrace();
            return false;
        }
    }

    @Override
    public void stopEncode() {
        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
        bufferInfo.flags = 4;
        encodeVideoSuccess(null, bufferInfo, 0);
        this.isStop = true;
        encode(null, ZFYMediaManager.getInstance().getPresentationTimeUs(), true);
        IGSMediaObserver<IGSNV12Consumer> iGSMediaObserver = this.observer;
        if (iGSMediaObserver != null) {
            iGSMediaObserver.onStop(this);
            this.observer = null;
        }
    }

    @Override
    public void addObserver(IGSMediaObserver<IGSNV12Consumer> iGSMediaObserver) {
        this.observer = iGSMediaObserver;
    }

    @Override
    public void onNV12Stream(byte[] bArr, long j) {
        if (this.isStop) {
            return;
        }
        encode(bArr, j, false);
    }

    public boolean encode(byte[] bArr, long j, boolean z) {
        try {
            int dequeueInputBuffer = this.mediaCodec.dequeueInputBuffer(1000L);
            if (dequeueInputBuffer < 0) {
                Log.w(TAG, "dequeueInputBuffer inputBufferIndex:" + dequeueInputBuffer);
            } else if (z) {
                this.mediaCodec.queueInputBuffer(dequeueInputBuffer, 0, 0, j, 4);
                Log.i(TAG, "queueInputBuffer BUFFER_FLAG_END_OF_STREAM");
            } else {
                ByteBuffer inputBuffer = this.mediaCodec.getInputBuffer(dequeueInputBuffer);
                if (inputBuffer != null && inputBuffer.capacity() >= bArr.length) {
                    inputBuffer.clear();
                    inputBuffer.put(bArr);
                    this.mediaCodec.queueInputBuffer(dequeueInputBuffer, 0, bArr.length, j, 0);
                }
                Log.i(TAG, "inputBuffer error");
                return false;
            }
        } catch (Exception e) {
            Log.w(TAG, "dequeueInputBuffer: " + e.getClass().getSimpleName());
        }
        while (true) {
            try {
                MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
                int dequeueOutputBuffer = this.mediaCodec.dequeueOutputBuffer(bufferInfo, 10000L);
                if (bufferInfo.flags == 2) {
                    ByteBuffer outputBuffer = this.mediaCodec.getOutputBuffer(dequeueOutputBuffer);
                    outputBuffer.position(bufferInfo.offset);
                    outputBuffer.limit(bufferInfo.offset + bufferInfo.size);
                    encodeVideoSuccess(copyDirectByteBuffer(outputBuffer), bufferInfo, dequeueOutputBuffer);
                    this.mediaCodec.releaseOutputBuffer(dequeueOutputBuffer, false);
                } else if (bufferInfo.flags == 4) {
                    Log.i(TAG, "flags == BUFFER_FLAG_END_OF_STREAM");
                    stopMediaCodec();
                    return true;
                } else if (dequeueOutputBuffer >= 0 && bufferInfo.size > 0) {
                    ByteBuffer outputBuffer2 = this.mediaCodec.getOutputBuffer(dequeueOutputBuffer);
                    outputBuffer2.position(bufferInfo.offset);
                    outputBuffer2.limit(bufferInfo.offset + bufferInfo.size);
                    encodeVideoSuccess(copyDirectByteBuffer(outputBuffer2), bufferInfo, dequeueOutputBuffer);
                    this.mediaCodec.releaseOutputBuffer(dequeueOutputBuffer, false);
                } else if (dequeueOutputBuffer != -2) {
                    return true;
                } else {
                    setOutputFormat();
                }
            } catch (Exception e2) {
                Log.w(TAG, "dequeueOutputBuffer " + e2.getClass().getSimpleName() + " " + j);
                return true;
            }
        }
    }

    @Override
    public void addLisener(IGSVideoEncoderConsumer iGSVideoEncoderConsumer) {
        IGSVideoEncoderConsumer iGSVideoEncoderConsumer2;
        this.listener = iGSVideoEncoderConsumer;
        if (this.cacheOutputFormate == null || (iGSVideoEncoderConsumer2 = this.listener) == null) {
            return;
        }
        iGSVideoEncoderConsumer2.setOutputFormat(this.cacheOutputFormate);
    }

    @Override
    public void removeLisener(IGSVideoEncoderConsumer iGSVideoEncoderConsumer) {
        this.listener = null;
    }

    @Override
    public boolean isStop() {
        return this.isStop;
    }

    public void setOutputFormat() {
        this.cacheOutputFormate = this.mediaCodec.getOutputFormat();
        IGSVideoEncoderConsumer iGSVideoEncoderConsumer = this.listener;
        if (iGSVideoEncoderConsumer != null) {
            iGSVideoEncoderConsumer.setOutputFormat(this.cacheOutputFormate);
        }
    }

    public void encodeVideoSuccess(ByteBuffer byteBuffer, MediaCodec.BufferInfo bufferInfo, int i) {
        fpsCount(TAG, "", bufferInfo.presentationTimeUs);
        IGSVideoEncoderConsumer iGSVideoEncoderConsumer = this.listener;
        if (iGSVideoEncoderConsumer != null) {
            iGSVideoEncoderConsumer.encodeVideoSuccess(GSMediaSampleData.createVideoSampleData(byteBuffer, bufferInfo));
        }
        if (bufferInfo.flags == 4) {
            this.listener = null;
            this.mediaCodec.stop();
            this.mediaCodec.release();
            Log.i(TAG, "264编码器关闭");
            this.mediaCodec = null;
        }
    }
}
